package com.asura.app.wechat.base;

import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;

import com.asura.app.wechat.R;

/**
 * Created by Asura on 2017/12/29.
 */

public class AutoLoadMoreAdapterWrapper extends RecyclerView.Adapter {

    private final LayoutInflater mInflater;
    private RecyclerView.Adapter mRealAdapter;
    private boolean mAutoLoadMoreEnable = true;
    private OnAutoLoadMoreListener mListener;
    private RecyclerView.OnScrollListener mOnScrollListener;
    private boolean mIsLoadingMore;
    private int mAutoLoadMoreThreshold = 5;
    private int TYPE_LOAD_MORE = -999;

    public RecyclerView.Adapter getRealAdapter() {
        return mRealAdapter;
    }

    public AutoLoadMoreAdapterWrapper(Context context, RecyclerView.Adapter realAdapter) {
        mInflater = LayoutInflater.from(context);
        mRealAdapter = realAdapter;
        mRealAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onChanged() {
                AutoLoadMoreAdapterWrapper.this.notifyDataSetChanged();
            }

            @Override
            public void onItemRangeChanged(int positionStart, int itemCount) {
                AutoLoadMoreAdapterWrapper.this.notifyItemRangeChanged(positionStart, itemCount);
            }

            @Override
            public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
                AutoLoadMoreAdapterWrapper.this.notifyItemRangeChanged(positionStart, itemCount, payload);
            }

            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                AutoLoadMoreAdapterWrapper.this.notifyItemRangeInserted(positionStart, itemCount);
            }

            @Override
            public void onItemRangeRemoved(int positionStart, int itemCount) {
                AutoLoadMoreAdapterWrapper.this.notifyItemRangeRemoved(positionStart, itemCount);
            }

            @Override
            public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {

            }
        });
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_LOAD_MORE) {
            return new RecyclerHolder(mInflater.inflate(R.layout.item_load_more, parent, false));
        }
        return mRealAdapter.onCreateViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        int itemViewType = getItemViewType(position);
        if (itemViewType == TYPE_LOAD_MORE) {
            Animation animation = AnimationUtils.loadAnimation(holder.itemView.getContext(), R.anim.rotate_loading);
            ((RecyclerHolder) holder).getView(R.id.iv_loading).startAnimation(animation);
            return;
        }
        mRealAdapter.onBindViewHolder(holder, position);
    }

    @Override
    public int getItemViewType(int position) {
        if (mIsLoadingMore && position == getItemCount() - 1) {
            return TYPE_LOAD_MORE;
        }
        return mRealAdapter.getItemViewType(position);
    }

    @Override
    public int getItemCount() {
        return mRealAdapter.getItemCount() + (mIsLoadingMore ? 1 : 0);
    }

    @Override
    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
        mRealAdapter.onViewAttachedToWindow(holder);
        int itemViewType = getItemViewType(holder.getLayoutPosition());
        if (itemViewType == TYPE_LOAD_MORE) {
            ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
            if (layoutParams != null && layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
                ((StaggeredGridLayoutManager.LayoutParams) layoutParams).setFullSpan(true);
            }
        }
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        mRealAdapter.onAttachedToRecyclerView(recyclerView);
        if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
            GridLayoutManager gridLayoutManager = (GridLayoutManager) recyclerView.getLayoutManager();
            GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    int itemViewType = getItemViewType(position);
                    if (itemViewType == TYPE_LOAD_MORE) {
                        return ((GridLayoutManager) recyclerView.getLayoutManager()).getSpanCount();
                    }
                    if (spanSizeLookup != null) {
                        return spanSizeLookup.getSpanSize(position);
                    }
                    return 1;
                }
            });
        }
        mOnScrollListener = new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                //1. 没有正在加载
                //2. 当前滚动离最后剩几个
                //3. 必须超过一屏才行（一屏能显示为什么要分页？）
                if (canLoadMore() && dy > 0) {
                    RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();
                    int lastVisibleItemPosition = 0;
                    int lastItemPosition = lm.getItemCount() - 1;
                    if (lm instanceof LinearLayoutManager) {
                        lastVisibleItemPosition = ((LinearLayoutManager) lm).findLastVisibleItemPosition();
                    }
                    if (lm instanceof GridLayoutManager) {
                        GridLayoutManager gridLayoutManager = (GridLayoutManager) lm;
                        lastVisibleItemPosition = gridLayoutManager.findLastVisibleItemPosition();
                    }
                    if (lm instanceof StaggeredGridLayoutManager) {
                        int[] infos = new int[((StaggeredGridLayoutManager) lm).getSpanCount()];
                        ((StaggeredGridLayoutManager) lm).findLastVisibleItemPositions(infos);
                        lastVisibleItemPosition = findMax(infos);
                    }
                    int gap = lastItemPosition - lastVisibleItemPosition;
                    if (gap > 0 && gap <= mAutoLoadMoreThreshold) {
                        mIsLoadingMore = true;
                        recyclerView.post(() -> notifyItemInserted(lm.getItemCount() - 1));
                        if (mListener != null) {
                            mListener.onAutoLoadMore();
                        }
                    }
                }
            }
        };
        recyclerView.addOnScrollListener(mOnScrollListener);
    }

    private int findMax(int[] infos) {
        int max = infos[0];
        for (int i = 1; i < infos.length; i++) {
            if (infos[i] > max) {
                max = infos[i];
            }
        }
        return max;
    }


    @Override
    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
        recyclerView.removeOnScrollListener(mOnScrollListener);
        super.onDetachedFromRecyclerView(recyclerView);
    }

    private boolean canLoadMore() {
        return mAutoLoadMoreEnable && !mIsLoadingMore;
    }


    public void setAutoLoadMoreEnable(boolean enable) {
        if (!enable && mIsLoadingMore) {
            setAutoLoadMoreFinish();
        }
        mAutoLoadMoreEnable = enable;
    }

    public void setAutoLoadMoreFinish() {
        if (mIsLoadingMore) {
            notifyItemRemoved(getItemCount() - 1);
        }
        mIsLoadingMore = false;
    }

    public void setAutoLoadMoreThreshold(int threshold) {
        mAutoLoadMoreThreshold = threshold;
    }

    public void setOnLoadMoreListener(OnAutoLoadMoreListener listener) {
        mListener = listener;
    }

    public interface OnAutoLoadMoreListener {
        void onAutoLoadMore();
    }
}
